﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EuroManager.Domain.Simulator.Result;
using NUnit.Framework;

namespace EuroManager.Domain.Simulator.Tests.Result
{
    [TestFixture]
    public class GameDataTests
    {
        private GameData data;

        [SetUp]
        public void SetUp()
        {
            data = new GameData();
        }

        [Test]
        public void ShouldExposeBallData()
        {
            Assert.IsNotNull(data.Ball);
        }

        [Test]
        public void ShouldAddPlayer()
        {
            int number = 3;
            data.AddPlayer(GameTeam.Team2, number);

            Assert.IsTrue(data.Players.Any(p => p.Team == GameTeam.Team2 && p.Number == number));
        }

        [Test]
        public void ShouldAddMultiplePlayers()
        {
            data.AddPlayer(GameTeam.Team1, 5);
            data.AddPlayer(GameTeam.Team2, 7);
            data.AddPlayer(GameTeam.Team1, 7);

            Assert.AreEqual(3, data.Players.Length);
        }

        [Test]
        public void ShouldAddPlayerFrameLocation()
        {
            float x = 30;
            float y = 17;

            data.AddPlayer(GameTeam.Team1, 5);
            data.AddPlayerFrame(GameTeam.Team1, 5, x, y, 50);

            Assert.IsTrue(data.Players.Single().X.Contains(x));
            Assert.IsTrue(data.Players.Single().Y.Contains(y));
        }

        [Test]
        public void ShouldAddPlayerFrameAngle()
        {
            float angle = 35;

            data.AddPlayer(GameTeam.Team2, 1);
            data.AddPlayerFrame(GameTeam.Team2, 1, 3, 25, angle);

            Assert.IsTrue(data.Players.Single().Angle.Contains(angle));
        }

        [Test]
        public void ShouldUpdateTime()
        {
            int frameIndex = 50;
            data.UpdateTime(frameIndex);

            Assert.IsTrue(data.TimeUpdates.Contains(frameIndex));
        }

        [Test]
        public void ShouldUpdateTimeMultipleTimes()
        {
            data.UpdateTime(3);
            data.UpdateTime(18);
            data.UpdateTime(59);

            Assert.AreEqual(3, data.TimeUpdates.Length);
        }

        [Test]
        public void ShouldUpdateTeam1Score()
        {
            int frameIndex = 5;
            data.UpdateScore(GameTeam.Team1, frameIndex);

            Assert.IsTrue(data.Score1Updates.Contains(frameIndex));
        }

        [Test]
        public void ShouldUpdateTeam2Score()
        {
            int frameIndex = 21;
            data.UpdateScore(GameTeam.Team2, frameIndex);

            Assert.IsTrue(data.Score2Updates.Contains(frameIndex));
        }
        
        [Test]
        public void ShouldUpdateScoreMultipleTimes()
        {
            data.UpdateScore(GameTeam.Team2, 30);
            data.UpdateScore(GameTeam.Team2, 58);
            data.UpdateScore(GameTeam.Team1, 94);
            data.UpdateScore(GameTeam.Team2, 101);
            data.UpdateScore(GameTeam.Team1, 102);

            Assert.AreEqual(2, data.Score1Updates.Length);
            Assert.AreEqual(3, data.Score2Updates.Length);
        }

        [Test]
        public void ShouldAddHighlight()
        {
            int startFrame = 54;
            int endFrame = 68;

            data.AddHighlight(startFrame, endFrame);

            Assert.IsTrue(data.Highlights.Any(h => h.StartFrame == startFrame && h.EndFrame == endFrame));
        }

        [Test]
        public void ShouldAddMultipleHighlights()
        {
            data.AddHighlight(13, 27);
            data.AddHighlight(35, 42);
            data.AddHighlight(59, 67);

            Assert.AreEqual(3, data.Highlights.Count());
        }

        [Test]
        public void ShouldMergeIntersectingHighlights()
        {
            data.AddHighlight(7, 25);
            data.AddHighlight(18, 31);

            HighlightData highlight = data.Highlights.Single();

            Assert.AreEqual(7, highlight.StartFrame);
            Assert.AreEqual(31, highlight.EndFrame);
        }

        [Test]
        public void ShouldIgnoreHighlightsContainedInOthers()
        {
            data.AddHighlight(8, 94);
            data.AddHighlight(25, 32);

            HighlightData highlight = data.Highlights.Single();

            Assert.AreEqual(8, highlight.StartFrame);
            Assert.AreEqual(94, highlight.EndFrame);
        }
    }
}
